package com.carlife.provider;

import java.util.ArrayList;
import java.util.List;

import com.carlife.exception.LogicException;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class DBEngineer {
	
	protected SQLiteDatabase db = null;
	private DBHelper dbHelper = null;
	protected Context ctx = null;
	
	public DBEngineer(Context ctx) {
		super();
		this.ctx = ctx;
		this.dbHelper = new DBHelper(ctx);
	}
	
	protected void open() {
		this.db = this.dbHelper.getWritableDatabase();		
	}
	
	protected void close() {
		this.db.close();
	}
	
	public void insert(IModel model) {
		open();
		try {
			insertInner(model);
		} finally {
			close();
		}
		
	}
	
	public void update(IModel model) {
		open();
		try {
			updateInner(model);
		} finally {
			close();
		}
	}
	
	public void delete(IModel model) {
		open();
		try {
			deleteInner(model);
		} finally {
			close();
		}
	}
	
	public IModel load(IModel model) {
		open();
		try {
			return loadInner(model);
		} finally {
			close();
		}
	}
	
	public List<IModel> query(IModel model, Conditions cond) {
		open();
		try {
			return queryInner(model, cond);
		} finally {
			close();
		}
	}
	
	
	protected void insertInner(IModel model) {
		this.db.beginTransaction();
		try {
			this.db.insert(model.getModelName(), null, model.getContentValues());
			this.db.setTransactionSuccessful();
		} finally {
			this.db.endTransaction();
		}
	}
	
	
	
	protected void updateInner(IModel model) {
		this.db.beginTransaction();
		try {
			this.db.update(
					model.getModelName(), 
					model.getContentValues(), 
					model.getPKCondition().getPrepareWhereClause(), 
					model.getPKCondition().getPrepareArguments());
			this.db.setTransactionSuccessful();
		} finally {
			this.db.endTransaction();
		}
	}
	
	protected void deleteInner(IModel model) {
		this.db.beginTransaction();
		try {
			this.db.delete(
					model.getModelName(), 
					model.getPKCondition().getPrepareWhereClause(), 
					model.getPKCondition().getPrepareArguments());
			this.db.setTransactionSuccessful();
		} finally {
			this.db.endTransaction();
		}
	}
	
	protected IModel loadInner(IModel model) {
		List<IModel> reslt = queryInner(model, model.getPKCondition());
		if (reslt.size() >0) {
			return reslt.get(0);
		} else {
			throw new LogicException("NotFoundException : " + model.getPKCondition().toString());
		}
	}
	
	protected List<IModel> queryInner(IModel model, Conditions cond) {
		this.db.beginTransaction();
		try {
			Cursor cursor = 
				this.db.query(
					model.getModelName(), 
					cond.getColumns(),
					cond.getPrepareWhereClause(), 
					cond.getPrepareArguments(),
					null,  // group by
					null,  // have
					cond.getOrderClause(),
					(cond.getLimit() == 0)?null:String.valueOf(cond.getLimit()));
			List<IModel> rslt = new ArrayList<IModel>();
			if (cursor.moveToFirst()) {
				do {
					rslt.add(parseModel(model, cursor));
				} while (cursor.moveToNext());
			}
			
			return rslt;
		} finally {
			this.db.endTransaction();
		}
	}
	
	
	private IModel parseModel(IModel model, Cursor cursor) {
		return model.pareseNewModel(cursor);		
	}
}
